package com.bxl.netty.rpc.server.context;

import com.bxl.netty.rpc.client.common.client.AppInfo;
import com.bxl.netty.rpc.client.common.client.ClientInfo;
import com.bxl.netty.rpc.client.common.pool.ZoneClientPool;
import com.bxl.netty.rpc.client.common.rule.PollLoadBalance;
import com.bxl.netty.rpc.common.Lifecycle;
import com.bxl.netty.rpc.common.context.Context;
import com.bxl.netty.rpc.common.filter.Filter;
import com.bxl.netty.rpc.common.message.MsgResponseContent;
import com.bxl.netty.rpc.common.message.PackageMsg;
import com.bxl.netty.rpc.common.serialize.KryoSerialize;
import com.bxl.netty.rpc.common.serialize.Serialize;
import com.bxl.netty.rpc.common.util.HandlerFactory;
import com.bxl.netty.rpc.register.client.RegisterClientContext;
import com.bxl.netty.rpc.register.client.RegisterClientContextImpl;
import com.bxl.netty.rpc.server.filter.FilterChain;
import com.bxl.netty.rpc.register.server.common.server.Server;
import com.bxl.netty.rpc.server.ServerMsgDecoder;
import com.bxl.netty.rpc.server.ServerMsgEncoder;
import com.bxl.netty.rpc.server.handler.ServerHandler;
import com.bxl.netty.rpc.server.register.BeanRegister;

import java.util.ArrayList;
import java.util.List;

/**
 * <>
 *
 * @author baixl
 * @date 2021/2/25
 */
public class ServerContextImpl implements BeanServerContext, Lifecycle {
    private Lifecycle server;
    private FilterChain chain;
    private Serialize serialize;

    private List<HandlerFactory> decoder;
    private List<HandlerFactory> handler;
    private List<HandlerFactory> encoder;


    private ZoneClientPool clientPool;
    private RegisterClientContext registerClient;

    private int port = 5555;

    public ServerContextImpl(int port) {
        this.port = port;
    }

    public List<HandlerFactory> getHandler() {
        return handler;
    }

    public void setHandler(List<HandlerFactory> handler) {
        this.handler = handler;
    }

    public ServerContextImpl init() {
        filterInit();
        configSerialize();
        configDecoder();
        configEncoder();
        configHandler();
        configRegister();
        return this;
    }

    /**
     * 可以更改为通过扫描路径实例化进行注册。
     *
     * @param interfaces
     * @param bean
     */
    public void registerBean(Class interfaces, Object bean) {
        if (interfaces.isAssignableFrom(bean.getClass())) {
            BeanRegister.register(interfaces, bean);
        }
    }

    /**
     * 如果有多台注册中心，注册多台。
     */
    protected void configRegister() {
        this.registerClient = new RegisterClientContextImpl();
        this.registerClient.init();
        this.clientPool = new ZoneClientPool();

        AppInfo zoneInfo = new AppInfo();
        zoneInfo.setApp("register");
        List<ClientInfo> clients = new ArrayList<ClientInfo>();
        //可以添加多个注册中心
        clients.add(new ClientInfo("register", "localhost", 7777, this.registerClient));
        zoneInfo.setClients(clients);
        zoneInfo.setLoadBalance(new PollLoadBalance());
        this.clientPool.addZone(zoneInfo);

    }


    protected void configDecoder() {
        decoder = new ArrayList<HandlerFactory>();
        decoder.add(new HandlerFactory<Context>(ServerMsgDecoder.class));
    }

    protected void configHandler() {
        handler = new ArrayList<HandlerFactory>();
        handler.add(new HandlerFactory<Context>(ServerHandler.class));
    }

    protected void configEncoder() {
        encoder = new ArrayList<HandlerFactory>();
        encoder.add(new HandlerFactory<Context>(ServerMsgEncoder.class));
    }

    public void registerFilter(Filter filter) {
        if (chain == null) {
            chain = new FilterChain();
        }
        chain.registerFilter(filter);
    }

    /**
     * 可以修改为配置化
     */
    protected void configSerialize() {
        serialize = new KryoSerialize();
    }

    /**
     * 可以修改为支持拦截器的配置化
     */
    protected void filterInit() {
        if (chain == null) {
            chain = new FilterChain();
        }
    }

    public void start() {
        server = new Server(port, this, true);
        server.start();
    }

    public void stop() {
        server.stop();
        System.exit(1);
    }

    public Lifecycle getServer() {
        return server;
    }

    public void setServer(Lifecycle server) {
        this.server = server;
    }

    public FilterChain getChain() {
        return chain;
    }

    public String getApp() {
        return "localhost";
    }

    public void setChain(FilterChain chain) {
        this.chain = chain;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public Serialize getSerialize() {
        return serialize;
    }

    public void setSerialize(Serialize serialize) {
        this.serialize = serialize;
    }

    public List<HandlerFactory> getDecoder() {
        return decoder;
    }

    public void setDecoder(List<HandlerFactory> decoder) {
        this.decoder = decoder;
    }

    public List<HandlerFactory> getEncoder() {
        return encoder;
    }

    public void setEncoder(List<HandlerFactory> encoder) {
        this.encoder = encoder;
    }

    public ZoneClientPool getClientPool() {
        return clientPool;
    }

    public void setClientPool(ZoneClientPool clientPool) {
        this.clientPool = clientPool;
    }
}
